//
// Created by shubo on 2020/2/6.
//

#include "me_order.h"

order_t* order_t::create(
        uint64_t id,
        uint32_t type,
        uint32_t side,
        const char *market,
        const char *source,
        uint32_t user_id,
        mpd_t  *amount,
        mpd_t  *price,
        mpd_t  *taker_fee,
        mpd_t  *maker_fee)
{
    order_t *order = (order_t*)malloc(sizeof(order_t));
    if (order == NULL) {
        return NULL;
    }
    order->id           = id;
    order->type         = type;
    order->side         = side;
    order->create_time  = current_timestamp();
    order->update_time  = order->create_time;
    order->market       = strdup(market);
    order->source       = strdup(source);
    order->user_id      = user_id;
    order->price        = mpd_new(&mpd_ctx);
    order->amount       = mpd_new(&mpd_ctx);
    order->taker_fee    = mpd_new(&mpd_ctx);
    order->maker_fee    = mpd_new(&mpd_ctx);
    order->left         = mpd_new(&mpd_ctx);
    order->freeze       = mpd_new(&mpd_ctx);
    order->deal_stock   = mpd_new(&mpd_ctx);
    order->deal_money   = mpd_new(&mpd_ctx);
    order->deal_fee     = mpd_new(&mpd_ctx);

    mpd_copy(order->amount, amount, &mpd_ctx);
    mpd_copy(order->left, amount, &mpd_ctx);
    mpd_copy(order->price, price, &mpd_ctx);
    mpd_copy(order->taker_fee, taker_fee, &mpd_ctx);
    mpd_copy(order->maker_fee, maker_fee, &mpd_ctx);

    mpd_copy(order->freeze, mpd_zero, &mpd_ctx);
    mpd_copy(order->deal_stock, mpd_zero, &mpd_ctx);
    mpd_copy(order->deal_money, mpd_zero, &mpd_ctx);
    mpd_copy(order->deal_fee, mpd_zero, &mpd_ctx);

    return order;
}

void order_t::release()
{
    mpd_del(this->price);
    mpd_del(this->amount);
    mpd_del(this->taker_fee);
    mpd_del(this->maker_fee);
    mpd_del(this->left);
    mpd_del(this->freeze);
    mpd_del(this->deal_stock);
    mpd_del(this->deal_money);
    mpd_del(this->deal_fee);
    free(this->market);
    free(this->source);
    free(this);
}

json_t *get_order_info(order_t *order)
{
    json_t *info = json_object();
    json_object_set_new(info, "id", json_integer(order->id));
    json_object_set_new(info, "market", json_string(order->market));
    json_object_set_new(info, "source", json_string(order->source));
    json_object_set_new(info, "type", json_integer(order->type));
    json_object_set_new(info, "side", json_integer(order->side));
    json_object_set_new(info, "user", json_integer(order->user_id));
    json_object_set_new(info, "ctime", json_real(order->create_time));
    json_object_set_new(info, "mtime", json_real(order->update_time));

    json_object_set_new_mpd(info, "price", order->price);
    json_object_set_new_mpd(info, "amount", order->amount);
    json_object_set_new_mpd(info, "taker_fee", order->taker_fee);
    json_object_set_new_mpd(info, "maker_fee", order->maker_fee);
    json_object_set_new_mpd(info, "left", order->left);
    json_object_set_new_mpd(info, "deal_stock", order->deal_stock);
    json_object_set_new_mpd(info, "deal_money", order->deal_money);
    json_object_set_new_mpd(info, "deal_fee", order->deal_fee);

    return info;
}

int order_match_compare(const void *value1, const void *value2)
{
    const order_t *order1 = (order_t*)value1;
    const order_t *order2 = (order_t*)value2;

    if (order1->id == order2->id) {
        return 0;
    }
    if (order1->type != order2->type) {
        return 1;
    }

    int cmp;
    if (order1->side == MARKET_ORDER_SIDE_ASK) {
        cmp = mpd_cmp(order1->price, order2->price, &mpd_ctx);
    } else {
        cmp = mpd_cmp(order2->price, order1->price, &mpd_ctx);
    }
    if (cmp != 0) {
        return cmp;
    }

    return order1->id > order2->id ? 1 : -1;
}

int order_id_compare(const void *value1, const void *value2)
{
    const order_t *order1 = (order_t*)value1;
    const order_t *order2 = (order_t*)value2;
    if (order1->id == order2->id) {
        return 0;
    }
    return order1->id > order2->id ? -1 : 1;
}